package com.newly.center.business.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.newly.api.sys.feign.AuthEntityClient;
import com.newly.center.business.service.CheckRecordService;
import com.newly.center.business.service.CompanyService;
import com.newly.center.business.service.SiteService;
import com.newly.common.base.constants.AuthConstant;
import com.newly.common.base.constants.CommonConstant;
import com.newly.common.base.entity.R;
import com.newly.common.base.entity.auth.ICurrentTenant;
import com.newly.common.base.entity.business.Dto.CheckRecordDto;
import com.newly.common.base.entity.business.Dto.CompanyDto;
import com.newly.common.base.entity.business.Po.CheckRecord;
import com.newly.common.base.entity.business.Po.Company;
import com.newly.common.base.entity.business.Po.Site;
import com.newly.common.base.entity.business.Vo.CheckRecordVo;
import com.newly.common.base.entity.business.Vo.DetailsVo;
import com.newly.common.base.entity.business.Vo.OverweightNumVo;
import com.newly.common.base.entity.business.Vo.RecordVo;
import com.newly.common.base.exception.NewlyException;
import com.newly.common.core.utils.CopyUtil;
import com.newly.common.core.utils.PageUtil;
import com.newly.common.core.utils.RequestUtils;
import com.newly.common.mapper.business.CompanyMapper;
import com.newly.common.mapper.sys.AuthEntityMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @anthor sbq
 * @date 2021/10/27 10:52
 */
@Service("companyService")
public class CompanyServiceImpl extends ServiceImpl<CompanyMapper, Company> implements CompanyService {

    @Autowired
    private AuthEntityMapper entityMapper;
    @Autowired
    private CheckRecordService checkRecordService;
    @Autowired
    private SiteService siteService;

    @Autowired
    private AuthEntityClient authEntityClient;

    @Autowired
    private CompanyMapper companyMapper;

    @Autowired
    private RequestUtils requestUtils;

    @Override
    public PageUtil getPage(ICurrentTenant currentTenant, CompanyDto companyDto) {
        List<Company> companyList;
        Page<Company> page = new Page<>(companyDto.getPageNum(), companyDto.getPageSize());
        //获取数据范围
        List<String> entityIds = currentTenant.getEntityIds(AuthConstant.AuthEntityType.COMPANY);
        if (ObjectUtil.isEmpty(entityIds))
            return new PageUtil(page);
        QueryWrapper<Company> q = new QueryWrapper<>();
        q.lambda().like(StringUtils.isNotBlank(companyDto.getName()), Company::getName, companyDto.getName());
        q.lambda().in(Company::getId, entityIds);
        q.lambda().eq(Company::getIsDeleted, 0);
        q.lambda().orderByDesc(Company::getId);
        page = this.page(page, q);
        if (page.getRecords().isEmpty())
            return new PageUtil(page);
        companyList = page.getRecords();
        List<Long> companyIds = companyList.stream().map(Company::getId).collect(Collectors.toList());
        //获取带有超重次数的站点列表
        List<Site> siteList = this.siteService.countOverweightNum(companyDto.getOffset(), companyIds);
        List<OverweightNumVo> overweightNumVos = new ArrayList<>();
        //按企业id分组
        Map<Long, List<Site>> map = siteList.stream().collect(Collectors.groupingBy(Site::getCompanyId));
        for (Map.Entry<Long, List<Site>> entry : map.entrySet()) {
            OverweightNumVo overweightNumVo = new OverweightNumVo();
            overweightNumVo.setId(entry.getKey());
            overweightNumVo.setOverweightNum(entry.getValue().stream().mapToInt(Site::getOverweightNum).sum());
            overweightNumVos.add(overweightNumVo);
        }
        //设置超重次数
        companyList = companyList.stream().map(p -> overweightNumVos.stream().filter(m ->
                Objects.equals(p.getId(), m.getId())).findFirst()
                .map(m -> {
                    p.setOverweightNum(m.getOverweightNum());
                    return p;
                }).orElse(p))
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        page.setRecords(companyList);
        return new PageUtil(page);
    }

    @Override
    public DetailsVo<Company> getDetailsById(Long id, Integer offset) {

        String startTime = DateUtil.offsetDay(DateUtil.date(), -offset).toString();
        DetailsVo<Company> detailsVo = new DetailsVo<>();
        List<RecordVo> recordVos = new ArrayList<>();
        Company company = this.getOne(new QueryWrapper<Company>().lambda().eq(Company::getId, id).eq(Company::getIsDeleted, 0));
        detailsVo.setEntity(company);
        detailsVo.setRecordVoList(recordVos);
        List<Site> siteList = this.siteService.list(new QueryWrapper<Site>().lambda().in(Site::getCompanyId, id));
        if (ObjectUtil.isEmpty(siteList))
            return detailsVo;
        List<Long> siteIds = siteList.stream().map(Site::getId).collect(Collectors.toList());
        CheckRecordDto checkRecordDto = new CheckRecordDto().setSiteIds(siteIds).setStartTime(startTime).setEndTime(DateUtil.now());
        List<CheckRecord> checkRecordList = this.checkRecordService.getListByCondition(checkRecordDto);
        List<CheckRecordVo> checkRecordVoList = CopyUtil.copyList(checkRecordList, CheckRecordVo.class);
        checkRecordVoList = this.checkRecordService.cover(checkRecordVoList);
        for (CheckRecordVo checkRecordVo : checkRecordVoList) {
            RecordVo recordVo = new RecordVo()
                    .setId(checkRecordVo.getId())
                    .setSiteName(checkRecordVo.getSiteName())
                    .setRatio(checkRecordVo.getOverRate())
                    .setOverweightType(checkRecordVo.getOverweightType())
                    .setTime(new DateTime(checkRecordVo.getCreateTime()).toString());
            recordVos.add(recordVo);
        }
        detailsVo.setRecordVoList(recordVos);
        return detailsVo;
    }

    @Override
    public void edit(Company company) {

        this.updateById(company);
    }

    @Override
    public void save(Company company, ICurrentTenant currentTenant) {
        company.setCreateUser(currentTenant.getUserId());
        company.setCreateTime(DateUtil.now());
        this.save(company);
        //保存权限实体
     /*   AuthEntityPo authEntityPo = new AuthEntityPo();
        authEntityPo.setEntityId(company.getId().toString());
        authEntityPo.setType(EntityTypeEnum.企业.getCode());
        authEntityPo.setCreateTime(DateUtil.date());
        this.entityMapper.insert(authEntityPo);*/
        R r = authEntityClient.bind(AuthConstant.AuthEntityType.COMPANY, Arrays.asList(company.getId().toString()));
        System.out.println(r);
    }

    @Override
    public R delete(Long[] ids) {

        List<Company> companyList = this.list(new QueryWrapper<Company>().lambda().in(Company::getId, Arrays.asList(ids)));
        if (companyList.size() == 0)
            throw new NewlyException("企业id有误，请联系管理员！");
        List<Site> siteList = this.siteService.list(new LambdaQueryWrapper<Site>().in(Site::getCompanyId, Arrays.asList(ids)).eq(Site::getIsDeleted, 0));
        if (siteList.size() > 0)
            return R.fail(1, "企业名下有站点，不能删除！");
        companyList = companyList.stream().peek(t -> t.setIsDeleted(1)).collect(Collectors.toList());
        this.updateBatchById(companyList);
        //删除权限实体对应记录
//        List<AuthEntityPo> entityPos = this.entityMapper.selectList(new QueryWrapper<AuthEntityPo>().lambda().in(AuthEntityPo::getEntityId, Arrays.asList(ids)));
//        if (ObjectUtil.isEmpty(entityPos))
//            throw new NewlyException("企业id没有绑定到权限实体表，请联系管理员！");
//        List<Integer> entityIds = entityPos.stream().map(AuthEntityPo::getId).collect(Collectors.toList());
//        this.entityMapper.deleteBatchIds(entityIds);
//        R r = authEntityClient.unbind(AuthConstant.AuthEntityType.COMPANY, ConverseUtils.toString(ids));
//        log.debug(r.toString());

        return R.ok(0);
    }

    @Override
    public List<String> getCompanyNames() {
        List<String> companyNames = null;

        ICurrentTenant currentTenant = requestUtils.getCurrentTenant();
        List<String> entityIds = currentTenant.getEntityIds(AuthConstant.AuthEntityType.COMPANY);
        if (ObjectUtil.isEmpty(entityIds)) return companyNames;

        LambdaQueryWrapper<Company> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Company::getIsDeleted, CommonConstant.DeleteFlag.NO_DELETE.getCode());
        wrapper.in(Company::getId, entityIds);
        List<Company> companyList = this.list(wrapper);
        if (ObjectUtil.isEmpty(companyList)) return null;
//        List<Company> companyList = this.list(new QueryWrapper<Company>()
//                .lambda().eq(Company::getIsDeleted, 0).orderByAsc(Company::getId));
        companyNames = companyList.stream().map(Company::getName).collect(Collectors.toList());
        return companyNames;
    }

    @Override
    public boolean repeat(String companyName) {
        List<Company> companies = this.list(new QueryWrapper<Company>().lambda().eq(Company::getName, companyName).eq(Company::getIsDeleted, 0));
        return companies.size() > 0;
    }

    @Override
    public List<Company> getByIds(List<String> companyIds) {
        if (ObjectUtil.isEmpty(companyIds)) return null;
        LambdaQueryWrapper<Company> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(Company::getId, companyIds);
        wrapper.eq(Company::getIsDeleted, CommonConstant.DeleteFlag.NO_DELETE.getCode());
        return companyMapper.selectList(wrapper);
    }
}
